/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkStateGridAUt.h"
#include "MkEvent/MkEventPool.h"
#include "MkEvent/MkEvent.h"
#include "MkEvent/MkTimer.h"
#include "MkUtil/MkUtil.h"
#include "MkUtil/MkMemQueue.h"

CMkStateGridAUt::CMkStateGridAUt()
{

}

CMkStateGridAUt::~CMkStateGridAUt()
{

}

void CMkStateGridAUt::SetUp()
{
    m_pUpServer = nullptr;
    m_pCurServer = nullptr;
    m_WaitHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
    m_pEventPool = new CMkEventPool;
    m_pEventPool->Start(1);
    m_pTimer = new CMkTimer;
    m_pTimer->StartTimerThread();

    m_UpServerId = "191000000000000001";
    m_ServerId = "191000000000000002";
    m_UpServerRealm = "1910000000";
    m_Realm = "1910000000";

    m_pUpServer = new CMkStateGridA(m_pEventPool, m_pTimer);
    while (1) {
        m_UpServerPort = CMkUtil::GetRandomNumber() % 0xFFFF;
        if (NoneError == m_pUpServer->Start(m_UpServerId, m_UpServerRealm, "127.0.0.1", m_UpServerPort, [this](const CMkStateGridARequestBase* pRequest, const MkStateGridAResponseCallback& ResCb) {
            return OnUpRequest(pRequest, ResCb);
        })) {
            break;
        }
    }

    m_pCurServer = new CMkStateGridA(m_pEventPool, m_pTimer);
    while (1) {
        m_ServerPort = CMkUtil::GetRandomNumber() % 0xFFFF;
        if (NoneError == m_pCurServer->Start(m_ServerId, m_Realm, "127.0.0.1", m_ServerPort, [this](const CMkStateGridARequestBase* pRequest, const MkStateGridAResponseCallback& ResCb) {
            return OnCurRequest(pRequest, ResCb);
        })) {
            break;
        }
    }
}

Uint32 CMkStateGridAUt::OnUpRequest(const CMkStateGridARequestBase* pRequest, const MkStateGridAResponseCallback& ResCb)
{
    ResCb(MkSipStatusOK, nullptr);
    return NoneError;
}

Uint32 CMkStateGridAUt::OnCurRequest(const CMkStateGridARequestBase* pRequest, const MkStateGridAResponseCallback& ResCb)
{
    switch (pRequest->GetMsgType()) {
    case MkStateGridAMedia:
    {
        CMkStateGridAMediaResponse MediaRes("123", "127.0.0.1", 848, nullptr);
        ResCb(MkSipStatusOK, &MediaRes);
        return NoneError;
    }
    break;
    case MkStateGridASubscribe:
    {
        const CMkStateGridASubscribeRequest *pSubReq = dynamic_cast<const CMkStateGridASubscribeRequest*>(pRequest);
        if (pSubReq) {
            MkStateGridASubscribeType SubType = pSubReq->GetSubscribeType();
            MkString SubId = pSubReq->GetSubscribeId();
            m_pCurServer->GetEventPool()->GetFreeEvent()->AddPipTask([this, SubType,SubId]() {
                if (MkStateGridASubscribeAlarm == SubType) {
                    m_pCurServer->AlarmNotify(SubId, "active", "191000001110000002", "TestAlarm", 1, NowMkTime, NowMkTime, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
                        EXPECT_EQ(MkSipStatusOK, StatusCode);
                    });
                } else {
                    m_pCurServer->StateNotify(SubId, "active", "191000001110000002", "TestState", 1, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
                        EXPECT_EQ(MkSipStatusOK, StatusCode);
                    });
                }
            });

        }
    }
    default:
        break;
    }
    ResCb(MkSipStatusOK, nullptr);
    return NoneError;
}

void CMkStateGridAUt::TearDown()
{
    CMkThread::ThreadSleep(100);
    m_pTimer->StopTimerThread();
    m_pEventPool->Stop();
    m_pCurServer->Stop();
    m_pUpServer->Stop();
    CloseHandle(m_WaitHandle);
    MkDelete(m_pUpServer);
    MkDelete(m_pCurServer);
    MkDelete(m_pTimer);
    MkDelete(m_pEventPool);
}

TEST_F(CMkStateGridAUt, RealPlayTest)
{
    Uint32 ErrorCode = m_pUpServer->RealPlay("191000000000000002", "191000000000000002", FALSE, m_Realm, "127.0.0.1", m_ServerPort, "127.0.0.1", 424, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        const CMkStateGridAMediaResponse* pMediaRes = dynamic_cast<const CMkStateGridAMediaResponse*>(pResponse);
        EXPECT_NE(nullptr, pMediaRes);
        if (pMediaRes) {
            EXPECT_EQ(848, pMediaRes->GetRtpPort());
            EXPECT_STREQ("127.0.0.1", pMediaRes->GetRtpHost().c_str());
            m_PlaySession = pMediaRes->GetSessionId();
            if (pMediaRes->GetEventCb()) {
                pMediaRes->GetEventCb()(MkMapString(), "");
            }
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pUpServer->StopRealPlay(m_PlaySession, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}

TEST_F(CMkStateGridAUt, PtzControlTest)
{
    Uint32 ErrorCode = m_pUpServer->PtzControl("191000000000000002", "191000000000000002", m_Realm, "127.0.0.1", m_ServerPort, MkStateGridPtzUp, 1, 1, 1, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);

    ErrorCode = m_pUpServer->Ptz3DZoom("191000000000000002", "191000000000000002", m_Realm, "127.0.0.1", m_ServerPort, MkStateGridPtz3DZoom, 1, 1, 1, 1, 1, 1, 1, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}

TEST_F(CMkStateGridAUt, AlarmSubscribeTest)
{
    MkMap<MkString, Uint32> MapSubId;
    MapSubId["191000000000000002"] = 1;
    Uint32 ErrorCode = m_pUpServer->AlarmSubscribe("191000000000000002", "191000000000000002", m_Realm, "127.0.0.1", m_ServerPort, 1, MapSubId, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        const CMkStateGridASubscribeResponse *pAlaramSubRes = dynamic_cast<const CMkStateGridASubscribeResponse*>(pResponse);
        EXPECT_NE(nullptr, pAlaramSubRes);
        if (pAlaramSubRes) {
            m_AlaramSubscribeId = pAlaramSubRes->GetSubscribeId();
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    CMkThread::ThreadSleep(100);  //wait notify
    m_pUpServer->StopAlarmSubscirbe(m_AlaramSubscribeId, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}

TEST_F(CMkStateGridAUt, StateSubscribeTest)
{
    MkVectorString VecSubId;
    VecSubId.emplace_back("191000000000000002");
    Uint32 ErrorCode = m_pUpServer->StatusSubscribe("191000000000000002", "191000000000000002", m_Realm, "127.0.0.1", m_ServerPort, 1, VecSubId, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        const CMkStateGridASubscribeResponse *pStatusSubRes = dynamic_cast<const CMkStateGridASubscribeResponse*>(pResponse);
        EXPECT_NE(nullptr, pStatusSubRes);
        if (pStatusSubRes) {
            m_StatusSubscribeId = pStatusSubRes->GetSubscribeId();
        }
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
    CMkThread::ThreadSleep(100);  //wait notify
    m_pUpServer->StopStatusSubscirbe(m_StatusSubscribeId, [this](const MkSipStatus& StatusCode, const CMkStateGridAResponseBase* pResponse) {
        EXPECT_EQ(MkSipStatusOK, StatusCode);
        SetEvent(m_WaitHandle);
    });
    EXPECT_EQ(ErrorCode, NoneError);
    WaitForSingleObject(m_WaitHandle, 0xFFFF);
}